package com.qf.serviceimpl;

import com.qf.constant.CacheConstants;
import com.qf.constant.StrategyConstants;
import com.qf.feign.CacheFeign;
import com.qf.model.StandardSubmit;
import com.qf.service.FilterChainService;
import com.qf.util.PushMsgUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Set;

/**
 * 限流策略
 *
 * **限流 : **限流规则如下
 *
 * - 五分钟内，禁止相同客户账户ID向同一手机号码下发相同的短信内容超过3条；
 * - 一小时内，禁止相同客户账户ID向同一手机号码下发相同的短信内容超过5条；
 * - 24小时内，禁止相同客户账户ID向同一手机号码下发相同的短信内容超过10条；
 * - 如果超限就把发送日志存到Elasticsearch，
 *   如果同时是HTTP的发送方式就模拟出状态报告推送给客户。
 *
 * @author Ypl
 * @version V1.0
 * @Project OctoberAndNovember
 * @Package com.qf.serviceimpl
 * @Description:
 * @Date 2022/11/10 10:50
 */
@SuppressWarnings("all")
@Service(value = "limitFiveMinutes")
@Slf4j
public class LimitFilterServiceImpl implements FilterChainService {

    @Autowired
    CacheFeign cacheFeign;
    //五分钟过期时间
    private final long expireSecond = 300L;

    @Autowired
    PushMsgUtil pushMsgUtil;

    @Override
    public boolean strategy(StandardSubmit standardSubmit) {
        log.debug("【限流策略】 开始执行");
        //获取kes 判断redis有多少条数据
        Set<String> keys = cacheFeign.keys(CacheConstants.CACHE_PREFIX_SMS_LIMIT + standardSubmit.getClientID() + ":" + standardSubmit.getDestMobile() + ":" + standardSubmit.getMessageContent() + ":"+"*");
        if(keys.size()>2){
            // 发送失败 将日志存入MQ
            log.debug("【限流策略】 因余限流规则发送至报告");
            pushMsgUtil.sendLog(standardSubmit, StrategyConstants.STRATEGY_ERROR_LIMIT);
            pushMsgUtil.pushReport(standardSubmit,StrategyConstants.STRATEGY_ERROR_LIMIT);
            return false;
        }

        //设置键值的时间
        cacheFeign.set(CacheConstants.CACHE_PREFIX_SMS_LIMIT + standardSubmit.getClientID()+ ":" +standardSubmit.getDestMobile()+":"+standardSubmit.getMessageContent()+":"+ new Date().toString(),"1",expireSecond);
        //查找key，如果大于3个就不添加了
        log.debug("【限流策略】 开始执行");
        return true;
    }
}
